package com.tlvip.queue;

import lombok.Data;
import lombok.ToString;
import org.apache.commons.lang3.RandomUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Date;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

/**
 * <p>description：</p>
 * <p>copyright： copyright(C)2016-2099</p>
 * <p>Life is short,we need passion</p>
 * <p>Summary： </p>
 * <p>instructions： </p>
 * Date 1/16/21</p>
 * Author mac
 *
 * @version 1.0
 */
public class DelayQueueTest {
    private final Logger LOG = LoggerFactory.getLogger(DelayQueueTest.class);

    private static DelayQueue<DelayTaskItem> delayQueue = new DelayQueue<>();

    public static void main(String[] args) {
        DelayQueueTest delayQueueTest = new DelayQueueTest();
        DelayQueueTest.TaskForRunSync taskForRunSync = delayQueueTest.new TaskForRunSync();
        new Thread(taskForRunSync).start();
    }

    class TaskForRunSync implements Runnable {
        @Override
        public void run() {
            runReportTaskAsync();
        }
    }

    public void runReportTaskAsync() {
        LOG.info("runReportTaskAsync start...");
        String desc = "refresh data in irregularity interval";
        while (true) {
            try {
                if (delayQueue.size() == 0) {
                    doSyncDataFromBigData();
                } else {
                    DelayTaskItem waitToRun = delayQueue.take();
                    LOG.info("get task from delayQuery currentTime:{},delayTaskItem:{}", new Date(), waitToRun);
                    doSyncDataFromBigData();
                }
            } catch (Exception e) {
                LOG.error("delay to refresh data occ error:", e);
            } finally {
                delayQueue.put(new DelayTaskItem(getNextTime(), desc));
            }
        }
    }

    private long getNextTime() {
        // 单位 ms
        int randomMillSec = RandomUtils.nextInt(1000, 3000);
        long nextTime = System.currentTimeMillis() + randomMillSec;
        return nextTime;
    }

    private void doSyncDataFromBigData() {
        LOG.info("doSyncDataFromBigData");
    }

    @Data
    @ToString
    static class DelayTaskItem implements Delayed {
        private long time;

        private String desc;

        public DelayTaskItem(long time, String desc) {
            this.time = time;
            this.desc = desc;
        }

        @Override
        public long getDelay(TimeUnit unit) {
            return time - System.currentTimeMillis();
        }

        @Override
        public int compareTo(Delayed o) {
            DelayTaskItem delayTaskItem = (DelayTaskItem) o;
            long diff = time - delayTaskItem.getTime();
            if (diff <= 0) {
                return 1;
            } else {
                return -1;
            }
        }
    }
}
